package com.ytktt.study.week9.task3.rpcfx.server.config;

import com.ytktt.study.week9.task3.rpcfx.annotation.RpcfxServiceProvider;
import com.ytktt.study.week9.task3.rpcfx.api.RpcfxResolver;
import com.ytktt.study.week9.task3.rpcfx.api.ServiceProviderDesc;
import com.ytktt.study.week9.task3.rpcfx.api.resolver.ReflectGenericResolver;
import com.ytktt.study.week9.task3.rpcfx.constant.RpcfxConstant;
import com.ytktt.study.week9.task3.rpcfx.registry.Registry;
import com.ytktt.study.week9.task3.rpcfx.server.RpcfxInvoker;
import com.ytktt.study.week9.task3.rpcfx.server.RpcfxServer;
import com.ytktt.study.week9.task3.rpcfx.server.netty.NettyServer;
import com.ytktt.study.week9.task3.rpcfx.server.properties.RpcfxServerProperties;
import com.ytktt.study.week9.task3.rpcfx.utils.StringFormatUtils;
import org.reflections.Reflections;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Set;

/**
 * 服务器配置
 *
 * @author ytk
 */
@Configuration
public class ServerConfig {

    private final String host;

    public ServerConfig() throws UnknownHostException {
        this.host = InetAddress.getLocalHost().getHostAddress();
    }

    @Bean
    public RpcfxServer rpcfxServer(RpcfxServerProperties rpcfxServerProperties, RpcfxInvoker rpcfxInvoker, Registry registry) throws Exception {
        Reflections refs = new Reflections(RpcfxConstant.SERVICE_PACKAGE_PREFIX);
        Set<Class<?>> rpcfxServiceClassSet = refs.getTypesAnnotatedWith(RpcfxServiceProvider.class);
        for (Class<?> clazz : rpcfxServiceClassSet) {
            RpcfxServiceProvider anno = clazz.getAnnotation(RpcfxServiceProvider.class);
            // 目前这样要求只能实现一个接口
            String serviceName = StringFormatUtils.lowerFirstLetter(clazz.getInterfaces()[0].getSimpleName());
            ServiceProviderDesc serviceProviderDesc = ServiceProviderDesc.builder()
                    .host(this.host).port(rpcfxServerProperties.getPort())
                    .serviceName(serviceName).group(anno.group()).version(anno.version()).build();
            registry.registryService(serviceProviderDesc);
        }
        return new NettyServer(rpcfxServerProperties, rpcfxInvoker);
    }

    @Bean
    public RpcfxInvoker createInvoker(RpcfxResolver resolver){
        return new RpcfxInvoker(resolver);
    }

    @Bean
    public RpcfxResolver createResolver(){
//        return new DemoResolver();
        return new ReflectGenericResolver();
    }
}
